/*
 *@# FlashLink Created on 2004-7-23
 *
 *
 * Copyright: Bluejay Networks Inc. & Inquiry Management Systems Ltd.  2004
 *
 * This software is the proprietary information of Bluejay Networks Inc. & 
 * Inquiry Management Systems Ltd.  
 * Use is subject to license terms.
 */
package com.ims.iaa.AD;

import com.ims.iaa.IaaDebug; 
import com.ims.iaa.IaaUtil; 
import com.ims.iaa.URLUtil;
import com.ims.iaa.swf.SwfDecompiler;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Timestamp;
import java.util.List;

/**
 * This class represents flash link data collected by spiders. 
 * @author ShengMeng Bai
 *
 * @version 1.00, 23 JUL. 2004
 */
public class FlashLink extends AdDataLink {
	
	private int m_iSrcReqStatus = CONN_NEVER;
	
	//the web page URL which contain the flash
	private URL m_ContainerUrl;
	//the flash URL
	private URL m_SrcUrl;
	//the User Agent string used during the search process
	private String m_sUserAgent;
	//cookie to save the flash
	/*private*/public  transient SimpleCookies m_Cookie;
	//the flash object, contain data, size
	private AdFlash m_flash;
	//the host URL which contain the flash, which set at connectToResource()
	private String m_sFlashSite;
	// the time of connecting to the flash.
	private Timestamp m_objCollectTime;
	private boolean m_bOnlyParseURL = false;
	//HrefParser m_hrefParser = null;
	private URL m_objTargetUrl;

	private URL m_objRealTargetUrl;

	/**
	 * The constructor construct new Flash Link, 
	 * 
	 * @param srcUrl 				the flash URL.
	 * @param ContainerUrl			the web page URL which contain the flash
	 * @param sCodeBase 			The position of Flash Player ActiveX.
	 * 
	 * @return void
	 */
	public FlashLink(URL srcUrl, URL ContainerUrl, String sCodeBase){
		m_SrcUrl = srcUrl;
		m_ContainerUrl = ContainerUrl;
		m_flash = new AdFlash();
		m_flash.setCodeBase( sCodeBase );
		//Flash usually is advertisement.
		incPossibility(100);
	}
	/**
	 * The constructor construct updated Flash impression, 
	 * @param sSrc, Flash URL
	 * @param iImpID, the impression ID which saved in database
	 * @param iImageID, the image ID which saved in database
	 * @param sUserAgent
	 * 
	 * @see com.ims.iaa.SpiderDBConnectionImpl#getReConnectImp(int)
	 */
	public FlashLink(URL urlSRC, int iImpID, int iImageID, String sUserAgent){
		m_flash = new AdFlash();
		m_SrcUrl = urlSRC;
		setOldImpressionID(iImpID);
		setOldImageID(iImageID);
		setUserAgent(sUserAgent);
	}
	/**
	 * The constructor construct a object to parse Flash URL, 
	 * @param sSrc, Flash URL
	 * @param iImpID, the impression ID which saved in database
	 * @param iImageID, the image ID which saved in database
	 * @param sUserAgent
	 * 
	 * @see com.ims.iaa.SpiderDBConnectionImpl#getUnparsedFlashImp(int)
	 */
	public FlashLink(URL ContainerUrl, URL urlSRC, int iImpID, int iImageID, String sUserAgent, AdFlash data){
	    m_ContainerUrl = ContainerUrl;
	    m_flash = data;
		m_SrcUrl = urlSRC;
		setOldImpressionID(iImpID);
		setOldImageID(iImageID);
		setUserAgent(sUserAgent);
		m_bOnlyParseURL = true;
	}
	/**
	 * Get the advertisement type, it is "FLASH" or "FLASH/POPUP". 
	 * @return
	 */
	public String getAdType()  {
		if(isPopupData()){
			return ADTYPE_POPUP_FLASH;
		}else{
			return ADTYPE_FLASH;
		}
	}
	/**
	 * becase we also new the instance while parese the flash URL,
	 * use the funcion to distinct it.
	 * @return
	 */
	public boolean onlyParseURL(){
	    return m_bOnlyParseURL;
	}
	/**
	 * get AdFlash object.
	 */
	public AdData getAdData(){
		return m_flash;
	}
	/**
	 * Set the flash height, it should get from
	 * the web page which container the flash.
	 * 
	 * @param iHeight flash height in pixels
	 * 
	 * @return void
	 */
	public void setHeight( int iHeight ){
		m_flash.setHeight( iHeight );
	}
	/**
	 * Get the flash height
	 * @return flash height in pixels
	 */
	public int getHeight(){
		return m_flash.getHeight();
	}
	
	/**
	 * set the flash width, it should get from
	 * the web page which container the flash
	 * 
	 * @param iWidth flash width in pixels
	 * 
	 * @return void
	 */
	public void setWidth( int iWidth ){
		m_flash.setWidth( iWidth );
	}
	/**
	 * Get the flash width
	 * @return flash width in pixels
	 */
	public int getWidth(){
		return m_flash.getWidth();
	}
	/**
	 * Set the User Agent string which used during the search process
	 * @param agent
	 */
	public void setUserAgent(String sAgent)  {
		m_sUserAgent = sAgent;
	}
	/**
	 * Get the source URL of the flash.
	 * @return 
	 */
	public URL getSrcURL(){
		return m_SrcUrl;
	}
	/**
	 * Get the source URL string of the flash.
	 * @return 
	 */
	public String getSrcURLStr(){
		return m_SrcUrl.toExternalForm();
	}
	
	/**
	 * Get the host URL of the flash source.
	 * @return
	 */
	public String getAdDataSite(){
		return m_sFlashSite;
	}
	/**
	 * Get the web URL which this flash is showed.
	 * @return
	 */
	public URL getContainerURL(){
		return m_ContainerUrl;
	}
	//we cann't get the target url from web, return null;
	public String getRealTargetURLStr() {
	    if(m_objRealTargetUrl != null){
	        return m_objRealTargetUrl.toExternalForm();
	    }
	    return null;
	}
	//we cann't get the target url from web, return null;
	public URL getTargetURL(){
	    return m_objTargetUrl;
	}
	//we cann't get the target url from web, return null;
	public String getTargetURLStr(){
	    if(m_objTargetUrl != null){
		    return m_objTargetUrl.toExternalForm();
	    }
	    return null;
	}
	
	/**
	 * Get the position of Flash Player ActiveX.
	 * @return the String of the position of Flash Player ActiveX.
	 */
	public String getCodeBase(){
		return m_flash.getCodeBase();
	}
	
	/**
	 * The host URL advertiser, usualy, this infomation will be got through
	 * click the flash when flash is playing, but we cann't get it from web,
	 * so it may be null.
	 * 
	 * @return null
	 * @author ShengMeng Bai at 2004-07-24
	 */
	public String getAdvertiser(){
	    if(m_objRealTargetUrl != null){
		    return m_objRealTargetUrl.getHost();
	    }
	    return null;
	}
		
	public Timestamp getCollectTime() {
		// collectTime was set in the connectToRecources()  method;
		return m_objCollectTime;
	}
	/**
	 * Get the state of linked to falsh, 
	 * it may be CONN_NEVER, CONN_SUCCESS, CONN_BAD_URL, CONN_FAILURE
	 * 
	 * @return
	 */
	public int getSrcReqStatus(){
		return m_iSrcReqStatus;
	}
//++ changsheng 
	public void setCollectTime(Timestamp objCollectTime)
	{
	    this.m_objCollectTime = objCollectTime ;
	}
	
	public void setAdDataSite(String sFlashSite)
	{
	    this.m_sFlashSite = sFlashSite ;
	}
	
	public void setSrcReqStatus(int srcReqStatus)
	{
	    this.m_iSrcReqStatus = srcReqStatus ;
	}
//--
	
	
	/**
	 * Connect the flash to get some parammeter
	 */
	private void connectToResource() {
		// try to get the flash source content.
		URLConnection uc = null;
		m_Cookie = new SimpleCookies();
		try  {
		    //++modify by ShengMengBai at 2004-05-31
		    //because some image(flash) url maybe not real url, redirect it.
		    HrefParser href = new HrefParser(m_SrcUrl, m_sUserAgent);
		    if(!href.connect()){
				m_iSrcReqStatus = CONN_FAILURE;
		        return;
		    }
		    //get the redirect URL
		    m_SrcUrl = href.getRedirectURL();
		    //get uc
			uc = href.getConnection();
			
			m_Cookie.readCookies( uc );

			m_flash.setDataSize(href.getContentLength());
			//get the correct mimetype.
			m_flash.setDataType("application/x-shockwave-flash");
			//
			m_sFlashSite = uc.getURL().getHost();
			//++modify by ShengMengBai at 2004-05-31
			m_iSrcReqStatus = CONN_SUCCESS;
			
		} catch( Exception e ){
			m_iSrcReqStatus = CONN_FAILURE;
			if( IaaDebug.Debug ) {
				IaaUtil.log("!!!!Error make connection to the flash " + e);
			}
		}

		m_objCollectTime = new Timestamp(  System.currentTimeMillis() );
		if ( AdFlash.SAVEFLASH && (m_flash.getDataSize() < AdFlash.MAXFLASHSIZE )) {
			if(IaaDebug.AuxDebug)IaaDebug.begin("connect to the flash ");		
			try  {
				IaaDebug.begin("getInputStream for flash" + uc.getURL());
				BufferedInputStream bs = new BufferedInputStream(uc.getInputStream());
				IaaDebug.end("getInputStream " + uc.getURL());
	
				byte[] buf = new byte[1024];
				int readNum =0;

				ByteArrayOutputStream picOutStream = new ByteArrayOutputStream();

				IaaDebug.begin("read flash inputStream " + uc.getURL());
				while ( (readNum = bs.read(buf)) != -1)  {
						picOutStream.write(buf,0,readNum);
				}
				bs.close();
				IaaDebug.end("read flash inputStream " + uc.getURL());

				m_flash.setData(picOutStream.toByteArray());
				IaaDebug.end("set flash data");

				picOutStream.close();
				if(IaaDebug.AuxDebug)IaaDebug.end("connect to the flash ");		
			} catch ( Exception e ) {
				m_iSrcReqStatus = CONN_FAILURE;
				IaaUtil.log( "!!!!Get flash form the connection input stream error " + e );
			}
		} else {
			if(IaaDebug.Debug) IaaUtil.log("Flash data too big to save");	
			//Note: either flash is too big or we do not want to save the image, 
			// then the flashData is still null
		}
	}
	/* (non-Javadoc)
	 * @see com.ims.iaa.AD.AdDataLink#parse(java.util.List)
	 */
	public boolean parse(List lstAgency,List lstAdSize) {
		connectToResource();
		return true;
	}
	/* (non-Javadoc)
	 * @see com.ims.iaa.AD.AdDataLink#isConnectSuccessful()
	 */
	public boolean isConnectSuccessful() {
		if(m_iSrcReqStatus == CONN_SUCCESS){
			return true;
		}else{
			return false;
		}
	}
	public boolean parseURL(){
	    boolean bParse = false;
	    HrefParser hrefParser = null;
	    //if the AdFlash don't contain the URL or URL var, parse it again
	    if(!m_flash.hasFlashURL() && !m_flash.hasFlashURLVar()){
	        bParse = true;
	        IaaUtil.log("parse flash data which id=" + getOldImageID());
		    SwfDecompiler decp = new SwfDecompiler();
		    try{
			    if(decp.parse(m_flash.getByteData(), m_flash.getDataSize())){
			        m_flash.setURLUnsavedFlag();
			        String sFirstURL = null;
			        HrefParser oFirstParser = null;
			        String sFirstVar = null;
			        //if the flash contain URL, try every one
			        //if successful, save the it
			        if(decp.containURL()){
			            List lst = decp.getURLList();
			            for(int i = 0; i < lst.size(); i++){
			                String sURL = (String)lst.get(i);
			                if(sFirstURL == null){
			                    sFirstURL = sURL;
			                }
			                hrefParser = tryURL(sURL);
			                if(oFirstParser == null){
			                    oFirstParser = hrefParser;
			                }
			                if(hrefParser != null && hrefParser.isConnectSuccessful()){
					            m_flash.setFlashURL(sURL);
						        IaaUtil.log("The flash data contain valid URL: " + m_flash.getFlashURL());
			                    break;
			                }
			            }
			            //if the oFirstParser is null, it means the URL is Malformed URL.
			            if (oFirstParser == null){
			                sFirstURL = "";
			            }
			        }
			        //if the flash don't contain URL, or it is failed to connect it, 
			        //try every var 
			        //if successful, save the it
	                if(hrefParser == null || !hrefParser.isConnectSuccessful()){
			            List lst = decp.getURLVarList();
			            for(int i = 0; i < lst.size(); i++){
			                String sVar = (String)lst.get(i);
			                if(sFirstVar == null){
			                    sFirstVar = sVar;
			                }
						    hrefParser = tryURLVar(sVar);
			                if(oFirstParser == null){
			                    oFirstParser = hrefParser;
			                }
			                if(hrefParser != null && hrefParser.isConnectSuccessful()){
					            m_flash.setFlashURLVar(sVar);
						        IaaUtil.log("The flash contain valid URL variable: " + m_flash.getFlashURLVar());
			                    break;
			                }
			            }
	                }
	                //if it is failed to connect to the URL, we also save it to the database
	                if(hrefParser == null || !hrefParser.isConnectSuccessful()){
		                if(sFirstURL != null){
				            m_flash.setFlashURL(sFirstURL);
		                }else{
				            m_flash.setFlashURLVar(sFirstVar);
		                }
	                    hrefParser = oFirstParser;
	                }
	                //if has not URL or URL var, set URL as "" to save to database.
			        if(!m_flash.hasFlashURL() && !m_flash.hasFlashURLVar()){
			            m_flash.setFlashURL("");
			        }
			    }else{
			        IaaUtil.log("Can not find the URL or URL variable from flash data, whose id=" + getOldImageID());
	                //if has not URL or URL var, set URL as "" to save to database.
			        if(!m_flash.hasFlashURL() && !m_flash.hasFlashURLVar()){
			            m_flash.setFlashURL("");
			        }
			        return false;
			    }
		    }catch(Exception e){
		        e.printStackTrace();
		        IaaUtil.log("parse flash exception: " + e);
                //if has not URL or URL var, set URL as "" to save to database.
		        if(!m_flash.hasFlashURL() && !m_flash.hasFlashURLVar()){
		            m_flash.setFlashURL("");
		        }
		        return false;
		    }
	    }else if(m_flash.hasFlashURL()){
		    String sURL = m_flash.getFlashURL();
	        IaaUtil.log("The AdFlash object contain URL: " + sURL);
		}else if(m_flash.hasFlashURLVar()){
	        String sVar = m_flash.getFlashURLVar();
	        IaaUtil.log("The AdFlash object contain URL variable: " + sVar);
	    }
		//if it is unparsed
		if(!bParse){
		    //parse the URL 
		    String sURL = null;
		    //if the flash file is not the first parsed, dont' save it.
	        if(m_flash.hasFlashURL()){
			    //sURL = m_flash.getFlashURL();
			    //hrefParser = tryURL(sURL);
	            return false;
		    }else if(m_flash.hasFlashURLVar()){
		        String sVar = m_flash.getFlashURLVar();
			    hrefParser = tryURLVar(sVar);
		    }
		}
        if(hrefParser == null){
            return false;
        }else{
		    m_objTargetUrl = hrefParser.getOriginalURL();
            if(hrefParser.isConnectSuccessful()){
		        m_objRealTargetUrl = hrefParser.getRedirectURL();
            }
            return true;
        }
	}
	private HrefParser tryURLVar(String sVar){
        String sURL = parseUrlVar(m_SrcUrl, sVar);
	    if(sURL == null){
	        IaaUtil.log("The flash URL don't contain variable: " + sVar);
	        return null;
	    }
	    return tryURL(sURL);
	}
	private HrefParser tryURL(String sURL){
	    HrefParser hrefParser = null;
	    try{
		    URL target = URLUtil.getURL(m_ContainerUrl, sURL);
		    hrefParser = new HrefParser(target, m_sUserAgent);
	        System.out.println("waiting to connect URL: " + target);
		    hrefParser.connect();
	    }catch(Exception e){
	        e.printStackTrace();
	        IaaUtil.log("parse flash exception: " + e);
	    }
	    return hrefParser;
	}
	public static String parseUrlVar(URL url, String sVar){
	    if(sVar == null || sVar.trim().equals("")){
	        return null;
	    }
	    String sQuery = url.getQuery();
	    if(sQuery == null){
	        return null;
	    }
	    int iIndex = sQuery.indexOf(sVar + "=");
	    if(iIndex > -1){
	        int iEnd = sQuery.indexOf("&", iIndex);
	        if(iEnd > -1){
	            sQuery = sQuery.substring(iIndex, iEnd);
	        }else{
	            sQuery = sQuery.substring(iIndex);
	        }
	        return sQuery.substring(sVar.length() + 1);
	    }
	    return null;
	}
	
	public String toString(){
	    return "FLASH: " + m_SrcUrl.toString();
	}
}
